package socks

import (
	"log"
	"net"
	"strconv"
	"sync"
)

type enum_callback func(conn SocketConnection) bool

type SocketServer interface {
	Open(avPort uint16) bool                       // 开启服务
	Close()                                        // 关闭
	Foreach(f enum_callback)                       // 遍历连接
	SendRawData(SockId int32, avBytes []byte) bool // 根据id 发送消息
	SendData(SockId int32, Data []byte) bool       // 直接发送数据
	GetConnectCount() int32                        // 获取连接总数
}

type socketServer struct {
	sockContext
	server          net.Listener
	rwMtx           sync.RWMutex
	connections     map[int32]*socketConnection
	isOpen          bool
	connectionCount int32
}

// override
func (ss *socketServer) procConnect(sockConn *socketConnection) {
	func() {
		ss.rwMtx.Lock()
		defer ss.rwMtx.Unlock()
		ss.connections[sockConn.id] = sockConn
		ss.connectionCount += 1
	}()

	ss.MsgHandler.OnConnect(sockConn)
}

// override
func (ss *socketServer) procDisconnect(sockConn *socketConnection) {

	func() {
		ss.rwMtx.Lock()
		defer ss.rwMtx.Unlock()
		delete(ss.connections, sockConn.id)
		ss.connectionCount -= 1
	}()

	ss.MsgHandler.OnDisconnect(sockConn)
}

// 遍历函数，返回 false 时遍历终止
func (svr *socketServer) Foreach(f enum_callback) {
	svr.rwMtx.RLock()
	defer svr.rwMtx.RUnlock()
	for _, v := range svr.connections {
		if !f(v) {
			break
		}
	}
}

func (svr *socketServer) SendData(SockId int32, avBytes []byte) bool {
	ret := false
	svr.rwMtx.RLock()
	defer svr.rwMtx.RUnlock()
	conn := svr.connections[SockId]
	if conn != nil {
		conn.SendData(avBytes)
		ret = true
	}
	return ret
}

func (svr *socketServer) SendRawData(SockId int32, avBytes []byte) bool {
	ret := false
	svr.rwMtx.RLock()
	defer svr.rwMtx.RUnlock()
	conn := svr.connections[SockId]
	if conn != nil {
		conn.SendRawData(avBytes)
		ret = true
	}
	return ret
}

func (ss *socketServer) process_accept() {
	for {
		conn, err := ss.server.Accept()

		if err != nil {
			log.Println("server accept error: ", err)
			break
		}

		if !ss.isOpen {
			log.Println("server is closed!")
			break
		}

		sockConn := createSocketConnection(conn)
		go ss.process_connection(sockConn)
	}
}

func (ss *socketServer) Close() {
	if ss.isOpen {
		ss.server.Close()
		ss.rwMtx.RLock()
		defer ss.rwMtx.RUnlock()

		for _, v := range ss.connections {
			v.Disconnect()
		}
		ss.isOpen = false
	}
}

func (ss *socketServer) GetConnectCount() int32 {
	return ss.connectionCount
}

func (ss *socketServer) Open(avPort uint16) bool {
	ret := false
	if !ss.isOpen {
		ss.isOpen = true

		tcpServer, err := net.Listen("tcp", ":"+strconv.Itoa(int(avPort)))
		if err != nil {
			log.Println("listen eror: ", err)
			return false
		}
		ss.server = tcpServer

		go ss.process_accept()
		ret = true
	}
	return ret
}

func NewSocketServer(avOpts SockOptions) SocketServer {
	avOpts.init() // 设置默认值

	server := &socketServer{
		connections: make(map[int32]*socketConnection),
		sockContext: sockContext{SockOptions: avOpts},
	}
	server.myConnHandler = server // 这里包装一下，事件不暴露给外面

	return server
}
